package com.bocloud.cmp.service.resource;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.dao.CloudServerDao;
import com.bocloud.cmp.dao.CloudVendorDao;
import com.bocloud.cmp.dao.DataStoreDao;
import com.bocloud.cmp.dao.HostSystemDao;
import com.bocloud.cmp.dao.ImageDao;
import com.bocloud.cmp.dao.NetworkCardDao;
import com.bocloud.cmp.dao.NetworkDao;
import com.bocloud.cmp.dao.NetworkHostDao;
import com.bocloud.cmp.dao.PortGroupDao;
import com.bocloud.cmp.dao.ResourceEventDao;
import com.bocloud.cmp.dao.ServerIpDao;
import com.bocloud.cmp.dao.SnapshotDao;
import com.bocloud.cmp.dao.StoreHostDao;
import com.bocloud.cmp.driver.providers.intf.MonitorProvider;
import com.bocloud.cmp.driver.providers.intf.ServerProvider;
import com.bocloud.cmp.driver.zteadapter.ZTEServerPerf;
import com.bocloud.cmp.entity.resource.CloudServer;
import com.bocloud.cmp.entity.resource.CloudVendor;
import com.bocloud.cmp.entity.resource.DataStore;
import com.bocloud.cmp.entity.resource.HostSystem;
import com.bocloud.cmp.entity.resource.Image;
import com.bocloud.cmp.entity.resource.Network;
import com.bocloud.cmp.entity.resource.NetworkCard;
import com.bocloud.cmp.entity.resource.NetworkHost;
import com.bocloud.cmp.entity.resource.PortGroup;
import com.bocloud.cmp.entity.resource.ResourceEvent;
import com.bocloud.cmp.entity.resource.ServerIp;
import com.bocloud.cmp.entity.resource.Snapshot;
import com.bocloud.cmp.enums.CloudHandler;
import com.bocloud.cmp.enums.VMStatus;
import com.bocloud.cmp.enums.VendorType;
import com.bocloud.cmp.enums.VolumeCategory;
import com.bocloud.cmp.interfaces.resource.CloudServerService;
import com.bocloud.cmp.model.CloudServerBean;
import com.bocloud.cmp.model.MonitorCategoryModel;
import com.bocloud.cmp.model.MonitorModel;
import com.bocloud.cmp.model.NetcardOperation;
import com.bocloud.cmp.model.OSMigrateModel;
import com.bocloud.cmp.model.ServerModel;
import com.bocloud.cmp.model.SnapshotModel;
import com.bocloud.cmp.model.VMBean;
import com.bocloud.cmp.service.model.OperateResult;
import com.bocloud.cmp.service.utils.ResourceEventPublisher;
import com.bocloud.cmp.service.utils.SyncVmwareUtils;
import com.bocloud.common.model.BsmResult;
import com.bocloud.common.model.GridBean;
import com.bocloud.common.model.Param;
import com.bocloud.common.model.SimpleBean;
import com.bocloud.common.utils.ArrayTool;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.GridHelper;
import com.bocloud.common.utils.JSONTools;
import com.bocloud.common.utils.ListTool;
import com.bocloud.common.utils.MapTools;
import com.bocloud.coordinator.harmony.HarmonyLock;
import com.bocloud.coordinator.harmony.LockFactory;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * 云主机实现类
 * 
 * @author DZG
 * @since V1.0 2016年9月12日
 */
@Service("cloudServerService")
public class CloudServerServiceImpl implements CloudServerService {

    private static Logger logger = LoggerFactory.getLogger(CloudServerServiceImpl.class);
    @Autowired
    private CloudServerDao cloudServerDao;
    @Autowired
    private CloudVendorDao cloudVendorDao;
    @Autowired
    private ResourceEventDao resourceEventDao;
    @Autowired
    private ImageDao imageDao;
    @Autowired
    private DataStoreDao dataStoreDao;
    @Autowired
    private HostSystemDao hostSystemDao;
    @Autowired
    private LockFactory lockFactory;
    @Autowired
    private SnapshotDao snapshotDao;
    @Autowired
    private ServerProvider serverProvider;
    @Autowired
    private StoreHostDao storeHostDao;
    @Autowired
    private NetworkDao networkDao;
    @Autowired
    private PortGroupDao portGroupDao;
    @Autowired
    private NetworkHostDao networkHostDao;
    @Autowired
    private NetworkCardDao networkCardDao;
    @Autowired
    private MonitorProvider monitorProvider;
    @Autowired
    private ResourceEventPublisher resourceEventPublisher;
    @Autowired
    private ServerIpDao serverIpDao;

    @Override
    public BsmResult list(int page, int rows, List<Param> params, Map<String, String> sorter, Boolean simple) {
        GridBean gridBean = null;
        try {
            if (null == params) {
                params = new ArrayList<>();
            }
            if (null == sorter || sorter.isEmpty()) {
                sorter = Maps.newHashMap();
                sorter.put("gmtCreate", Common.ONE);
            }

            int total = this.cloudServerDao.count(params);
            if (simple) {
                List<SimpleBean> beans = this.cloudServerDao.list(params, sorter);
                gridBean = new GridBean(1, 1, total, beans);
            } else {
                List<CloudServer> list = this.cloudServerDao.list(page, rows, params, sorter);
                for (CloudServer server : list) {
                    // 设置主机名称
                    HostSystem hostSystem = hostSystemDao.query(server.getHostId());
                    if (null != hostSystem) {
                        server.setHostName(hostSystem.getName());
                        server.setClusterName(hostSystem.getClusterName());
                    }
                    // 设置快照数量
                    List<Snapshot> snapshots = snapshotDao.listByVMid(server.getId());
                    List<ServerIp> serverIps = serverIpDao.querybyuuid(server.getInstanceId());
                    server.setServerIps(serverIps);
                    server.setSnapshotCount(snapshots.size());
                }
                gridBean = GridHelper.getBean(page, rows, total, list);
            }
            return new BsmResult(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("Query vm list fail:", e);
            return new BsmResult(false, "查询失败", null, null);
        }
    }

    @Override
    public BsmResult create(String params, Long userId) {
        try {
            JSONObject object = JSONTools.isJSONObj(params);
            Long vendorId = object.getLong(Common.ID);
            Long region = object.getLong(Common.REGION);
            String name = object.getString(Common.NAME);
            Long hostId = object.getLong("hostId");
            if (cloudServerDao.exists(name, vendorId)) {
                return new BsmResult(false, "此名称已存在!");
            }
            String remark = object.getString("remark");
            String password = object.getString("password");
            // 云供应商
            CloudVendor vendor = cloudVendorDao.query(vendorId);
            if (null == vendor) {
                logger.error("get cloudVendor failure!");
                return new BsmResult(false, "创建失败!");
            }
            ServerModel model = new ServerModel();
            model.setName(name);
            model.setRemark(remark);
            VendorType type = VendorType.valueOf(vendor.getType());
            switch (type) {
            case OPENSTACK:
                model.setAccount("root");
                model.setPassword(password);
                model.setNetworkId(object.getString("networkId"));
                model.setFlavorId(object.getString("flavorId"));
                model.setImageId(object.getString("imageId"));
                break;
            case ALIYUN:
                model.setAccount("root");
                model.setPassword(password);
                model.setRegionId(object.getString("regionId"));
                model.setZone(object.getString("zone"));
                model.setImageId(object.getString("imageId"));
                model.setInstanceType(object.getString("instanceType"));
                model.setSecurityGroupId(object.getString("securityGroupId"));
                model.setInternetChargeType(object.getString("internetChargeType"));
                Integer internetMaxBandwidthIn = 0;
                Integer internetMaxBandwidthOut = 0;
                if (object.containsKey("internetMaxBandwidthIn")) {
                    internetMaxBandwidthIn = object.getInteger("internetMaxBandwidthIn");
                }
                if (object.containsKey("internetMaxBandwidthOut")) {
                    internetMaxBandwidthOut = object.getInteger("internetMaxBandwidthOut");
                }
                model.setInternetMaxBandwidthIn(internetMaxBandwidthIn);
                model.setInternetMaxBandwidthOut(internetMaxBandwidthOut);
                Integer systemDiskSize = 0;
                if (object.containsKey("systemDiskSize")) {
                    systemDiskSize = object.getInteger("systemDiskSize");
                }
                model.setSystemDiskSize(systemDiskSize);
                String systemDiskCategory = object.getString("systemDiskCategory");
                if (StringUtils.isEmpty(systemDiskCategory)) {
                    model.setSystemDiskCategory("cloud");
                } else {
                    if (VolumeCategory.CLOUD.name().equals(systemDiskCategory)) {
                        model.setSystemDiskCategory("cloud");
                    } else if (VolumeCategory.EFFICIENCY.name().equals(systemDiskCategory)) {
                        model.setSystemDiskCategory("cloud_efficiency");
                    } else if (VolumeCategory.SSD.name().equals(systemDiskCategory)) {
                        model.setSystemDiskCategory("cloud_ssd");
                    }
                }
                String dataDisk = null;
                if (object.containsKey("dataDisk")) {
                    dataDisk = object.getString("dataDisk");
                }
                if (null != dataDisk) {
                    JSONArray jsonArray = new JSONArray();
                    List<Object> list = JSONArray.parseArray(dataDisk);
                    for (Object obj : list) {
                        JSONObject jsonObject = JSONObject.parseObject(obj.toString());
                        String dataDiskCategory = jsonObject.getString("dataDiskCategory");
                        if (dataDiskCategory.equals(VolumeCategory.CLOUD.name())) {
                            jsonObject.put("dataDiskCategory", "cloud");
                        } else if (dataDiskCategory.equals(VolumeCategory.EFFICIENCY.name())) {
                            jsonObject.put("dataDiskCategory", "cloud_efficiency");
                        } else if (dataDiskCategory.equals(VolumeCategory.SSD.name())) {
                            jsonObject.put("dataDiskCategory", "cloud_ssd");
                        } else {
                            jsonObject.put("dataDiskCategory", "cloud");
                        }
                        jsonArray.add(jsonObject);
                    }
                    model.setDataDisk(jsonArray.toJSONString());
                }
                break;
            case VMWARE:
                model.setTemplate(object.getString("template"));
                model.setCpu(object.getInteger("cpu"));
                model.setMemory(object.getInteger("memory") / 4 * 4);
                model.setDisk(object.getInteger("disk"));
                model.setHostName(object.getString("hostname"));
                model.setDatastore(object.getString("datastore"));
                List<NetcardOperation> operations = JSONObject.parseArray(object.getString("operations"),
                        NetcardOperation.class);
                model.setOperations(operations);
                HostSystem hostSystem = hostSystemDao.query(hostId);
                if (null == hostSystem) {
                    return new BsmResult(false, "宿主机不存在");
                }
                // 要创建的虚拟机的cpu核数不能超过所在宿主机的cpu核数
                if (model.getCpu() > hostSystem.getCpuCore()) {
                    return new BsmResult(false, "虚拟机cpu核数不能超过所在宿主机的cpu核数,所选宿主机cpu是" + hostSystem.getCpuCore() + "核");
                }
                model.setClusterName(hostSystem.getClusterName());
                model.setVdcName(hostSystem.getVdcName());
                break;
            case JDYUN:
                break;
            default:
                break;
            }
            return this.create(vendor, model, region, userId, "", hostId, object.getLong("storeId"),
                    object.getLong("templateId"));
        } catch (Exception e) {
            logger.error("create server error:", e);
            return new BsmResult(false, "创建失败!");
        }
    }

    @Override
    public BsmResult batchReboot(String params, Long userId) {
        String[] idArray = params.split(",");// 获取要重启的虚拟机
        if (ArrayTool.isEmpty(idArray)) {
            return new BsmResult(false, "没有需要重启的机器！", "没有需要重启的机器！");
        }
        try {
            for (String id : idArray) {
                CloudServer server = cloudServerDao.query(Long.parseLong(id));
                if (null == server || !"RUNNING".equalsIgnoreCase(server.getStatus())) {
                    continue;
                }
                restart(Long.parseLong(id), userId);// 重启要重启的虚拟机
            }
        } catch (Exception e) {
            logger.error("批量重启操作失败", e);
            return new BsmResult(false, "批量重启任务下发失败！");
        }
        return new BsmResult(true, "批量重启任务已下发，正在执行...");
    }

    @Override
    public BsmResult batchStart(String params, Long userId) {
        String[] idArray = params.split(",");// 获取要开启的虚拟机
        if (ArrayTool.isEmpty(idArray)) {
            return new BsmResult(false, "没有需要启动的机器！", "没有需要启动的机器！");
        }
        try {
            for (String id : idArray) {
                CloudServer server = cloudServerDao.query(Long.parseLong(id));
                // 关机状态下的虚拟机允许开启
                if (!"STOPPED".equalsIgnoreCase(server.getStatus())
                        && !"SUSPENDED".equalsIgnoreCase(server.getStatus())) {
                    continue;
                }
                start(Long.parseLong(id), userId);
            }
        } catch (Exception e) {
            logger.error("batch start server fail:", e);
            return new BsmResult(false, "批量启动任务已下发失败");
        }
        return new BsmResult(true, "批量启动任务已下发，正在执行...");
    }

    @Override
    public BsmResult batchStop(String params, Long userId) {
        String[] idArray = params.split(",");// 获取要停止的虚拟机的id
        if (ArrayTool.isEmpty(idArray)) {
            return new BsmResult(false, "没有需要停止的机器！", "没有需要停止的机器！");
        }
        try {
            for (String id : idArray) {
                CloudServer server = cloudServerDao.query(Long.parseLong(id));
                if (!"RUNNING".equalsIgnoreCase(server.getStatus())
                        && !"SUSPENDED".equalsIgnoreCase(server.getStatus())) {
                    continue;
                }
                stop(Long.parseLong(id), userId);// 停止虚拟机
            }
        } catch (Exception e) {
            logger.error("batch stop server fail:", e);
            return new BsmResult(false, "批量停止任务下发失败");
        }
        return new BsmResult(true, "批量停止任务已执下发，正在执行...");
    }

    @Override
    public BsmResult batchRemove(String params, Long userId) {
        String[] idArray = params.split(",");// 获取要删除的虚拟机的id
        if (ArrayTool.isEmpty(idArray)) {
            return new BsmResult(false, "没有需要删除的机器！", "没有需要删除的机器！");
        }
        try {
            for (String id : idArray) {
                CloudServer server = cloudServerDao.query(Long.parseLong(id));
                if (!"STOPPED".equalsIgnoreCase(server.getStatus())
                        && !"SUSPENDED".equalsIgnoreCase(server.getStatus())) {
                    continue;
                }
                remove(Long.parseLong(id), userId);// 删除虚拟机
            }
        } catch (Exception e) {
            logger.error("batch remove server fail:", e);
            return new BsmResult(false, "批量删除任务下发失败");
        }
        return new BsmResult(true, "批量删除任务已下发，正在执行...");
    }

    @Override
    public BsmResult clone(String params, Long userId) {
        try {
            JSONObject object = JSONTools.isJSONObj(params);
            CloudServer bean = JSONObject.parseObject(object.toJSONString(), CloudServer.class);
            Long id = bean.getId();
            String name = bean.getName();
            String remark = bean.getRemark();
            Long hostId = bean.getHostId();
            List<NetcardOperation> operations = bean.getOperations();
            CloudServer server = cloudServerDao.query(id);
            CloudVendor vendor = cloudVendorDao.query(server.getVendorId());
            if (null == vendor) {
                logger.error("get cloudVendor failure!");
                return new BsmResult(false, "获取云供应商失败");
            }
            if (cloudServerDao.exists(name, vendor.getId())) {
                return new BsmResult(false, "此名称已存在!");
            }
            HostSystem hostSystem = hostSystemDao.query(hostId);
            if (null == hostSystem) {
                logger.error("get hostSystem failure!");
                return new BsmResult(false, "克隆失败!");
            }
            // 判断虚拟机所处的宿主机是否处于维护模式
            HostSystem host = hostSystemDao.query(server.getHostId());
            if (host.isMaintain()) {
                logger.error("虚拟机所在宿主机处于维护模式下不允许克隆");
                return new BsmResult(false, "虚拟机所在宿主机处于维护模式下不允许克隆");
            }
            ServerModel model = new ServerModel();
            model.setName(name);
            model.setTemplate(server.getName());
            model.setHostName(hostSystem.getName());
            model.setDatastore(object.getString("datastore"));
            model.setCpu(server.getCpu());
            model.setMemory(server.getMemory() / 2 * 2);
            model.setDisk(server.getDisk());
            model.setClusterName(hostSystem.getClusterName());
            model.setVdcName(hostSystem.getVdcName());
            model.setRemark(remark);
            model.setOperations(operations);
            try {

                CloudServer cloudServer = JSONObject.parseObject(JSONObject.toJSONString(model), CloudServer.class);
                cloudServer.setStatus(VMStatus.BUILDING.name());
                cloudServer.setIsTemplate(false);
                cloudServer.setRegion(server.getRegion());
                cloudServer.setAccount(server.getAccount());
                cloudServer.setPassword(server.getPassword());
                cloudServer.preSave(userId, userId, vendor.getId(), hostId, null);
                cloudServerDao.save(cloudServer);
                // 启动一个线程从MQ上获取数据
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        String type = vendor.getType();
                        String operate = type.toLowerCase() + ".vm";
                        try {
                            BsmResult result = serverProvider.create(vendor.getUuid(), null, model);
                            ResourceEvent event = null;
                            String handler = CloudHandler.CLONE.name();
                            if (result.isSuccess() && null != result.getData()) {
                                event = new ResourceEvent(id, handler, "success", userId, new Date(), "VM");
                                String content = JSONObject.toJSONString(result.getData());
                                CloudServer server = JSONObject.parseObject(content, CloudServer.class);
                                cloudServer.setInstanceId(server.getInstanceId());
                                cloudServer.setUuid(server.getUuid());
                                cloudServer.setToolsInstalled(server.getToolsInstalled());
                                cloudServer.setToolsRunning(server.getToolsRunning());
                                cloudServer.setDatastores(server.getDatastores());
                                cloudServer.setManagerIp(server.getManagerIp());
                                String state = server.getStatus();
                                if ((state.equalsIgnoreCase(VMStatus.BUILDING.name())
                                        || state.equalsIgnoreCase("BUILD"))) {
                                    updateStatus(cloudServer, vendor.getUuid(), "", VendorType.valueOf(type));
                                } else {
                                    switch (VendorType.valueOf(type)) {
                                    case OPENSTACK:
                                        if (state.equalsIgnoreCase("active")) {
                                            cloudServer.setStatus(VMStatus.RUNNING.name());
                                        } else if (state.equalsIgnoreCase("stopped")
                                                || state.equalsIgnoreCase("shutoff")) {
                                            cloudServer.setStatus(VMStatus.STOPPED.name());
                                        } else if (state.equalsIgnoreCase("error")) {
                                            cloudServer.setStatus(VMStatus.EXCEPTION.name());
                                            event = new ResourceEvent(cloudServer.getId(), CloudHandler.CREATE.name(),
                                                    "fail", userId, new Date(), "VM");
                                        }
                                        break;
                                    case ALIYUN:
                                        if (state.equalsIgnoreCase("Running")) {
                                            cloudServer.setStatus(VMStatus.RUNNING.name());
                                        } else if (state.equalsIgnoreCase("Stopped")) {
                                            cloudServer.setStatus(VMStatus.STOPPED.name());
                                        }
                                        break;
                                    case VMWARE:
                                        if (state.equalsIgnoreCase("poweredOn")) {
                                            cloudServer.setStatus(VMStatus.RUNNING.name());
                                        } else if (state.equalsIgnoreCase("poweredOff")) {
                                            cloudServer.setStatus(VMStatus.STOPPED.name());
                                        }
                                        syncSubObject(hostSystem.getVdcId(), vendor.getId(), cloudServer.getId(),
                                                server.getStores(), server.getNetworks(), server.getNetcards(),
                                                server.getSnapshots(), userId);
                                        break;
                                    default:
                                        break;
                                    }
                                }
                                logger.info("Clone server {} success!", cloudServer.getName());
                                cloudServerDao.update(cloudServer);
                            } else {
                                logger.warn("Clone Server {} failed! clean useless data in database ",
                                        server.getName());
                                cloudServerDao.remove(cloudServer.getId(), userId);
                                event = new ResourceEvent(id, handler, "fail", userId, new Date(), "VM");
                            }
                            resourceEventDao.save(event);
                            String message = "克隆虚拟机失败：可能是宿主机的空间资源不够亦或是其他原因导致";
                            if (result.isSuccess()) {
                                message = "克隆虚拟机成功";
                            }
                            resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                                    MapTools.simpleMap("vendorId", vendor.getId()), userId));
                        } catch (Exception e) {
                            logger.error("Get Message Exception:", e);
                            resourceEventPublisher.send(new OperateResult(false, "克隆虚拟机失败", operate,
                                    MapTools.simpleMap("vendorId", vendor.getId()), userId));
                        }
                    }
                }).start();
                return new BsmResult(true, "克隆任务已经下发，正在执行……");
            } catch (Exception e) {
                logger.error("create failure:", e);
                return new BsmResult(false, "克隆失败!");
            }
        } catch (Exception e) {
            logger.error("create server error:", e);
            return new BsmResult(false, "克隆失败!");
        }
    }

    @Override
    public BsmResult migrate(String params, Long userId) {
        try {
            JSONObject object = JSONTools.isJSONObj(params);
            Long id = object.getLong(Common.ID);
            Long hostId = object.getLong("hostId");
            // 云供应商
            CloudServer server = cloudServerDao.query(id);
            CloudVendor vendor = cloudVendorDao.query(server.getVendorId());
            if (null == vendor) {
                logger.error("get cloudVendor and region failure!");
                return new BsmResult(false, "云供应商不存在");
            }
            ServerModel model = new ServerModel();
            model.setName(server.getName());
            HostSystem host = hostSystemDao.query(hostId);
            if (null == host) {
                return new BsmResult(false, "宿主机不存在");
            }
            model.setStatus(server.getStatus());
            model.setHostName(host.getName());
            model.setClusterName(host.getClusterName());
            model.setVdcName(host.getVdcName());
            model.setInstanceId(server.getInstanceId());
            new Thread(new Runnable() {
                @Override
                public void run() {
                    String operate = vendor.getType().toLowerCase() + ".vm";
                    try {
                        BsmResult result = serverProvider.migrate(vendor.getUuid(), null, model);
                        ResourceEvent event = null;
                        if (result.isSuccess()) {
                            server.setHostId(hostId);
                            server.setMenderId(userId);
                            cloudServerDao.update(server);
                            event = new ResourceEvent(id, "MIGRATE", "success", userId, new Date(), "VM");
                        } else {
                            event = new ResourceEvent(id, "MIGRATE", "fail", userId, new Date(), "VM");
                        }
                        resourceEventDao.save(event);
                        resourceEventPublisher.send(new OperateResult(result.isSuccess(), result.getMessage(), operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), userId));
                    } catch (Exception e) {
                        logger.error("migrate server error:", e);
                        resourceEventPublisher.send(new OperateResult(false, "虚拟机迁移失败", operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), userId));
                    }
                }
            }).start();
            return new BsmResult(true, "迁移任务已经下发，正在执行……");
        } catch (Exception e) {
            logger.error("create server error:", e);
            return new BsmResult(false, "迁移失败!");
        }
    }

    @Override
    public BsmResult OSMigrate(String params, Long userId) {
        JSONObject object = JSONTools.isJSONObj(params);
        Long id = object.getLong(Common.ID);
        Long serverId = object.getLong("serverId");
        Boolean live = object.getBoolean("live");
        OSMigrateModel migrate = new OSMigrateModel();
        migrate.setLive(live);
        if (null != live && live) {
            migrate.setBlockMigration(object.getBoolean("blockMigration"));
            migrate.setDiskOverCommit(object.getBoolean("diskOverCommit"));
            migrate.setHost(object.getString("hostId"));
        }
        try {
            CloudVendor cloudVendor = cloudVendorDao.query(id);
            CloudServer server = cloudServerDao.query(serverId);
            Map<String, Long> hostIdMap = getHostId(id);// add by ouyangwulin
                                                        // 获取hostId

            if (null == cloudVendor || null == server) {
                logger.error("get cloudVendor and region failure!");
                return new BsmResult(false, "迁移失败!");
            }
            migrate.setInstanceId(server.getInstanceId());
            new Thread(new Runnable() {
                @Override
                public void run() {
                    String operate = cloudVendor.getType().toLowerCase() + ".vm";
                    try {
                        BsmResult bsmResult = serverProvider.OSMigrate(cloudVendor.getUuid(), null, migrate);
                        ResourceEvent event = null;
                        if (bsmResult.isSuccess()) {
                            event = new ResourceEvent(serverId, "MIGRATE", "success", userId, new Date(), "VM");
                            VMBean bean = JSONObject.parseObject(JSONObject.toJSONString(bsmResult.getData()),
                                    VMBean.class);
                            BeanUtils.copyProperties(bean, server);
                            server.setHostName(bean.getHostName());
                            server.setHostId(hostIdMap.get(bean.getHostName()));
                            cloudServerDao.update(server);
                            resourceEventPublisher.send(new OperateResult(bsmResult.isSuccess(), bsmResult.getMessage(),
                                    operate, MapTools.simpleMap("vendorId", cloudVendor.getId()), userId));
                        } else {
                            event = new ResourceEvent(serverId, "MIGRATE", "fail", userId, new Date(), "VM");
                            resourceEventPublisher.send(new OperateResult(false, "虚拟机迁移失败！", operate,
                                    MapTools.simpleMap("vendorId", cloudVendor.getId()), userId));
                        }
                        resourceEventDao.save(event);
                    } catch (Exception e) {
                        logger.error("osmigrate server error:", e);
                        resourceEventPublisher.send(new OperateResult(false, "虚拟机迁移失败！", operate,
                                MapTools.simpleMap("vendorId", cloudVendor.getId()), userId));
                    }
                }
            }).start();
            return new BsmResult(true, "迁移任务已经下发，正在执行……");
        } catch (Exception e) {
            logger.error("get cloudvendor and reg error:", e);
            return new BsmResult(false, "虚拟机迁移失败");
        }
    }

    @Override
    public BsmResult snapshot(String params, Long userId) {
        String path = CloudServer.class.getSimpleName() + "_" + userId;
        HarmonyLock lock = null;
        try {
            lock = lockFactory.getLock(path);
            if (!lock.acquire(path, 10, TimeUnit.SECONDS)) {
                logger.warn("Get harmonyLock time out!");
                return new BsmResult(false, "请求超时", "", "");
            }
            JSONObject object = JSONTools.isJSONObj(params);
            if (null == object) {
                return new BsmResult(false, "创建快照失败!");
            }
            Long vendorId = object.getLong(Common.ID);
            Long id = object.getLong("serverId");
            String name = object.getString(Common.NAME);
            String remark = object.getString("remark");
            CloudServer server = cloudServerDao.query(id);
            if (null == server) {
                logger.error("Server {} doesnot exist in database!", id);
                return new BsmResult(false, "该虚拟机不存在");
            }
            CloudVendor vendor = cloudVendorDao.query(vendorId);
            if (null == vendor) {
                logger.warn("get cloudVendor failure!");
                return new BsmResult(false, "该云供应商不存在");
            }
            VendorType type = VendorType.valueOf(vendor.getType());
            switch (type) {
            case VMWARE:
                HostSystem host = hostSystemDao.query(server.getHostId());
                if (null == host) {
                    logger.warn("HostSystem data not exist");
                    return new BsmResult(false, "宿主机不存在");
                }
                if (host.isMaintain()) {
                    return new BsmResult(false, "该虚拟机所在宿主机处于维护模式下，无法执行创建快照任务");
                }
                break;
            default:
                break;
            }
            SnapshotModel model = new SnapshotModel(name, remark, "", server.getInstanceId());
            // 启动一个线程从MQ上获取数据
            new Thread(new Runnable() {
                @Override
                public void run() {
                    String operate = vendor.getType().toLowerCase() + ".vm";
                    try {
                        BsmResult result = serverProvider.snapshot(model, vendor.getUuid(), "");
                        ResourceEvent event = null;
                        if (result.isSuccess()) {
                            String content = JSONObject.toJSONString(result.getData());
                            switch (type) {
                            case OPENSTACK:
                                if (null != result.getData()) {
                                    Image image = JSONObject.parseObject(content, Image.class);
                                    image.preSave(userId, userId, vendorId);
                                    imageDao.save(image);
                                }
                                break;
                            case VMWARE:
                                if (null != result.getData()) {
                                    Snapshot snapshot = JSONObject.parseObject(content, Snapshot.class);
                                    snapshot.preSave(userId, userId, vendorId, id);
                                    snapshotDao.save(snapshot);
                                }
                                break;
                            default:
                                break;
                            }
                            event = new ResourceEvent(id, "SNAPSHOT", "success", userId, new Date(), "SNAPSHOT");
                        } else {
                            event = new ResourceEvent(id, "SNAPSHOT", "fail", userId, new Date(), "SNAPSHOT");
                        }
                        resourceEventDao.save(event);
                        resourceEventPublisher.send(new OperateResult(result.isSuccess(), result.getMessage(), operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), userId));
                    } catch (Exception e) {
                        logger.error("Get Message Exception:", e);
                        resourceEventPublisher.send(new OperateResult(false, "创建失败", operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), userId));
                    }
                }
            }).start();
            return new BsmResult(true, "创建任务已经下发，正在执行……");
        } catch (Exception e) {
            logger.error("create server error:", e);
            return new BsmResult(false, "创建失败!");
        } finally {
            if (null != lock) {
                lock.release();
            }
        }
    }

    /**
     * 创建虚拟机
     * 
     * @param paramMap
     * @param remark
     * @param vendorId
     * @param region
     * @param userId
     * @param password
     * @return
     */
    private BsmResult create(CloudVendor vendor, ServerModel model, Long region, Long userId, String regCode,
            Long hostId, Long storeId, Long templateId) {
        try {
            CloudServer cloudServer = JSONObject.parseObject(JSONObject.toJSONString(model), CloudServer.class);
            // 保存数据
            cloudServer.setStatus(VMStatus.BUILDING.name());
            cloudServer.setIsTemplate(false);
            cloudServer.setRegion(region);
            cloudServer.preSave(userId, userId, vendor.getId(), hostId, templateId);
            cloudServerDao.save(cloudServer);
            // 启动一个线程从MQ上获取数据
            new Thread(new Runnable() {
                private HostSystem hostSystem;

                @Override
                public void run() {
                    String operate = vendor.getType().toLowerCase() + ".vm";
                    try {
                        BsmResult result = serverProvider.create(vendor.getUuid(), null, model);
                        Long serverId = cloudServer.getId();
                        String handler = CloudHandler.CREATE.name();
                        // 操作记录
                        ResourceEvent event = null;
                        if (result.isSuccess() && null != result.getData()) {
                            event = new ResourceEvent(serverId, handler, "success", userId, new Date(), "VM");
                            String content = JSONObject.toJSONString(result.getData());
                            CloudServer server = JSONObject.parseObject(content, CloudServer.class);
                            cloudServer.setInstanceId(server.getInstanceId());
                            cloudServer.setUuid(server.getUuid());
                            cloudServer.setToolsInstalled(server.getToolsInstalled());
                            cloudServer.setToolsRunning(server.getToolsRunning());
                            cloudServer.setDisk(server.getDisk());
                            cloudServer.setMemory(server.getMemory());
                            cloudServer.setCpu(server.getCpu());
                            cloudServer.setDatastores(server.getDatastores());
                            String hostName = server.getHostName();
                            if (null != hostName) {
                                cloudServer.setHostName(hostName);
                                hostSystem = hostSystemDao.getByName(hostName, vendor.getId());
                                if (null != hostSystem) {
                                    cloudServer.setHostId(hostSystem.getId());
                                }
                            }
                            cloudServer.setManagerIp(server.getManagerIp());
                            cloudServer.setServerIps(server.getServerIps());
                            String state = server.getStatus();
                            VendorType type = VendorType.valueOf(vendor.getType());
                            if ((state.equalsIgnoreCase(VMStatus.BUILDING.name()) || state.equalsIgnoreCase("BUILD"))) {
                                updateStatus(cloudServer, vendor.getUuid(), regCode, type);
                            } else {
                                switch (type) {
                                case OPENSTACK:
                                    if (state.equalsIgnoreCase("EXCEPTION")) {
                                        event = new ResourceEvent(serverId, handler, "fail", userId, new Date(), "VM");
                                    } else if (state.equalsIgnoreCase(VMStatus.SUSPENDED.name())) {
                                        event = new ResourceEvent(serverId, handler, "fail", userId, new Date(), "VM");
                                    }
                                    cloudServer.setStatus(state);
                                    break;
                                case ALIYUN:
                                    if (state.equalsIgnoreCase("Running")) {
                                        cloudServer.setStatus(VMStatus.RUNNING.name());
                                    } else if (state.equalsIgnoreCase("Stopped")) {
                                        cloudServer.setStatus(VMStatus.STOPPED.name());
                                    }
                                    break;
                                case VMWARE:
                                    if (state.equalsIgnoreCase("poweredOn")) {
                                        cloudServer.setStatus(VMStatus.RUNNING.name());
                                    } else if (state.equalsIgnoreCase("poweredOff")) {
                                        cloudServer.setStatus(VMStatus.STOPPED.name());
                                    }
                                    hostSystem = hostSystemDao.query(hostId);
                                    syncSubObject(hostSystem.getVdcId(), vendor.getId(), cloudServer.getId(),
                                            server.getStores(), server.getNetworks(), server.getNetcards(),
                                            server.getSnapshots(), userId);
                                    break;
                                default:
                                    break;
                                }
                            }
                            List<ServerIp> serverips = cloudServer.getServerIps();
                            if (null != serverips) {
                                for (ServerIp serverIp : serverips) {
                                    serverIpDao.save(serverIp);
                                }
                            }
                            cloudServerDao.update(cloudServer);
                        } else {
                            event = new ResourceEvent(serverId, handler, "fail", userId, new Date(), "VM");
                            cloudServerDao.remove(cloudServer.getId(), userId);
                        }
                        resourceEventDao.save(event);
                        resourceEventPublisher.send(new OperateResult(result.isSuccess(), result.getMessage(), operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), userId));
                    } catch (Exception e) {
                        logger.error("Get Message Exception:", e);
                        resourceEventPublisher.send(new OperateResult(false, "添加虚拟机失败", operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), userId));
                    }
                }
            }).start();
            return new BsmResult(true, "创建任务已经下发，正在执行……");
        } catch (Exception e) {
            logger.error("create failure:", e);
            return new BsmResult(false, "创建失败!");
        }
    }

    /**
     * 同步新虚拟性下的各对象信息
     * 
     * @param vdcId
     * @param vendorId
     * @param server
     * @param datastores
     * @param networks
     * @throws Exception
     */
    private void syncSubObject(Long vdcId, Long vendorId, Long serverId, List<String> datastores, List<String> networks,
            List<NetworkCard> cards, List<Snapshot> snapshots, Long userId) throws Exception {
        // 数据中心的存储信息
        Map<String, Long> storeMap = new HashMap<>();
        List<DataStore> stores = dataStoreDao.listByVdc(vdcId);
        for (DataStore store : stores) {
            storeMap.put(store.getStoreVal(), store.getId());
        }
        // 数据中心的网络信息
        Map<String, Long> networkMap = Maps.newHashMap();
        Map<String, PortGroup> groupMap = Maps.newHashMap();
        List<Network> oldNetworks = networkDao.listByVdc(vdcId);
        for (Network network : oldNetworks) {
            networkMap.put(network.getNetworkVal(), network.getId());
            List<PortGroup> groups = portGroupDao.listByNetwork(network.getId());
            for (PortGroup group : groups) {
                groupMap.put(group.getGroupVal(), group);
            }
        }
        SyncVmwareUtils utils = new SyncVmwareUtils(cloudServerDao, dataStoreDao, hostSystemDao, snapshotDao,
                networkDao, null, storeHostDao, networkCardDao, portGroupDao, networkHostDao);
        // 同步存储
        utils.addStore(vendorId, serverId, userId, "VM", datastores, storeMap);
        // 同步网络
        utils.addNetwork(vendorId, serverId, userId, "VM", networks, networkMap, groupMap);
        // 同步网卡
        utils.addCard(vendorId, serverId, userId, "VM", cards, groupMap);
        // 同步快照
        utils.addSnapshot(vendorId, serverId, userId, snapshots);
    }

    /**
     * 更新状态
     * 
     * @param server
     * @param vendor
     * @param regCode
     * @param type
     * @throws Exception
     */
    private void updateStatus(CloudServer server, String vendor, String regCode, VendorType type) throws Exception {
        // // 添加资源
        String instanceId = server.getInstanceId();
        Long start = System.currentTimeMillis();
        boolean running = true;
        while (running) {
            BsmResult bsmResult = serverProvider.detail(instanceId, vendor, regCode);
            // 超时和延时
            if (System.currentTimeMillis() - start > 1000 * 60 * 10) {
                server.setStatus(VMStatus.EXCEPTION.name());
                running = false;
            }
            if (bsmResult.isSuccess()) {
                VMBean bean = JSONObject.parseObject(JSONObject.toJSONString(bsmResult.getData()), VMBean.class);
                if (!instanceId.equals(bean.getInstanceId())) {
                    continue;
                }
                String state = bean.getStatus();
                switch (type) {
                case OPENSTACK:
                    server.setStatus(state);
                    break;
                case ALIYUN:
                    if (state.equalsIgnoreCase("Running")) {
                        server.setStatus(VMStatus.RUNNING.name());
                    } else if (state.equalsIgnoreCase("Stopped")) {
                        server.setStatus(VMStatus.STOPPED.name());
                    }
                    break;
                case VMWARE:
                    if (state.equalsIgnoreCase("poweredOn")) {
                        server.setStatus(VMStatus.RUNNING.name());
                    } else if (state.equalsIgnoreCase("poweredOff")) {
                        server.setStatus(VMStatus.STOPPED.name());
                    }
                    break;
                default:
                    break;
                }
                if (!(server.getStatus().equalsIgnoreCase(VMStatus.BUILDING.name())
                        || server.getStatus().equalsIgnoreCase("BUILD"))) {
                    running = false;
                }
                Thread.sleep(3000L);
            }
        }
    }

    @Override
    public BsmResult modify(CloudServerBean bean, Long userId) {
        Long serverId = bean.getId();
        String path = CloudServer.class.getSimpleName() + "_" + serverId;
        HarmonyLock lock = null;
        try {
            lock = lockFactory.getLock(path);
            if (!lock.acquire(path, 10, TimeUnit.SECONDS)) {
                logger.warn("Get harmonyLock time out!");
                return new BsmResult(false, "请求超时");
            }
            CloudServer vm = this.cloudServerDao.query(serverId);
            if (null == vm) {
                logger.warn("CloudServer does not exist!");
                return new BsmResult(false, "id为[" + serverId + "]的云主机不存在");
            }
            CloudVendor vendor = cloudVendorDao.query(vm.getVendorId());
            if (null == vendor) {
                logger.error("get cloudVendor failure");
                return new BsmResult(false, "修改失败");
            }
            VendorType type = VendorType.valueOf(vendor.getType());
            ServerModel model = null;
            switch (type) {
            case OPENSTACK:
                vm.setName(bean.getName());
                model = JSONObject.parseObject(JSONObject.toJSONString(vm), ServerModel.class);
                break;
            case VMWARE:
                BeanUtils.copyProperties(bean, vm);
                HostSystem hostSystem = hostSystemDao.query(vm.getHostId());
                model = JSONObject.parseObject(JSONObject.toJSONString(vm), ServerModel.class);
                model.setHostName(hostSystem.getName());
                model.setVdcName(hostSystem.getVdcName());
                model.setMemory(bean.getMemory() / 4 * 4);
                if (model.getCpu() > hostSystem.getCpuCore()) {
                    return new BsmResult(false, "虚拟机cpu核数不能超过所在宿主机cpu核数，宿主机cpu为" + hostSystem.getCpuCore() + "核");
                }
                if (hostSystem.isMaintain()) {
                    return new BsmResult(false, "虚拟机所处宿主机处于维护模式下，不允许编辑");
                }
                break;
            default:
                break;
            }
            ServerModel serverModel = model;
            // 启动一个线程
            new Thread(new Runnable() {
                @Override
                public void run() {
                    BsmResult result = serverProvider.modify(vendor.getUuid(), null, serverModel);
                    ResourceEvent event = null;
                    String operate = vendor.getType().toLowerCase() + ".vm";
                    try {
                        if (result.isSuccess()) {
                            switch (type) {
                            case VMWARE:
                                String content = JSONObject.toJSONString(result.getData());
                                CloudServer server = JSONObject.parseObject(content, CloudServer.class);
                                // 同步该虚拟机和网络的关系
                                HostSystem hostSystem = hostSystemDao.query(vm.getHostId());
                                Map<String, Long> networkMap = Maps.newHashMap();
                                Map<String, PortGroup> groupMap = Maps.newHashMap();
                                List<Network> oldNetworks = networkDao.listByVdc(hostSystem.getVdcId());
                                for (Network network : oldNetworks) {
                                    networkMap.put(network.getNetworkVal(), network.getId());
                                    List<PortGroup> groups = portGroupDao.listByNetwork(network.getId());
                                    for (PortGroup group : groups) {
                                        groupMap.put(group.getGroupVal(), group);
                                    }
                                }
                                SyncVmwareUtils utils = new SyncVmwareUtils(cloudServerDao, dataStoreDao, hostSystemDao,
                                        snapshotDao, networkDao, null, storeHostDao, networkCardDao, portGroupDao,
                                        networkHostDao);
                                utils.mergeNetworkHost(vendor.getId(), serverId, "VM", server.getNetworks(), networkMap,
                                        groupMap);
                                // 同步该虚拟机下的虚拟网卡
                                List<NetworkCard> oldCards = networkCardDao.listByHost(serverId, "VM");
                                utils.syncNetworkCard(oldCards, server.getNetcards(), vendor.getId(), serverId, userId,
                                        "VM", groupMap);
                                break;
                            default:
                                break;
                            }
                            if (null != vm.getExtendDisk()) {
                                vm.setDisk(vm.getDisk() + vm.getExtendDisk());
                            }
                            vm.setMenderId(userId);
                            cloudServerDao.update(vm);
                            event = new ResourceEvent(vm.getId(), "UPDATE", "success", userId, new Date(), "VM");
                        } else {
                            event = new ResourceEvent(vm.getId(), "UPDATE", "fail", userId, new Date(), "VM");
                        }
                        resourceEventDao.save(event);
                        resourceEventPublisher.send(new OperateResult(result.isSuccess(), result.getMessage(), operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), userId));
                    } catch (Exception e) {
                        logger.error("modify cloud server error:", e);
                        resourceEventPublisher.send(new OperateResult(false, "编辑虚拟机失败", operate,
                                MapTools.simpleMap("vendorId", vendor.getId())));
                    }
                }
            }).start();
            return new BsmResult(true, "编辑任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("Modify cloudServer fail:", e);
            return new BsmResult(false, "编辑失败");
        } finally {
            if (null != lock) {
                lock.release();
            }
        }
    }

    @Override
    public BsmResult remove(Long id, Long userId) {
        String path = CloudServer.class.getSimpleName() + "_" + id;
        HarmonyLock lock = null;
        try {
            lock = lockFactory.getLock(path);
            if (!lock.acquire(path, 10, TimeUnit.SECONDS)) {
                logger.warn("Get harmonyLock time out!");
                return new BsmResult(false, "请求超时");
            }
            CloudServer server = cloudServerDao.get(id);
            if (null == server) {
                logger.warn("CloudServer data not exist");
                return new BsmResult(false, "数据不存在");
            }
            if (!server.getStatus().equals(VMStatus.SYNSEXCEPTION.name())) {
                if (server.getStatus().equals(VMStatus.RUNNING.name())) {
                    return new BsmResult(false, "开机状态的云主机不可以删除!");
                }
            }
            CloudVendor cloudVendor = cloudVendorDao.query(server.getVendorId());
            if (null == cloudVendor) {
                logger.error("get cloudVendor failure!");
                return new BsmResult(false, "删除失败!");
            }
            new Thread(new Runnable() {
                @Override
                public void run() {
                    String operate = cloudVendor.getType().toLowerCase() + ".vm";
                    try {
                        ResourceEvent event = null;
                        if (!server.getStatus().equals(VMStatus.SYNSEXCEPTION.name())) {
                            BsmResult bsmResult = serverProvider.remove(server.getInstanceId(), cloudVendor.getUuid(),
                                    null);
                            if (bsmResult.isSuccess()) {
                                // 删除快照
                                snapshotDao.removeByVm(id, userId);
                                storeHostDao.deleteByHost(server.getId(), "VM");
                                networkHostDao.deleteByHost(server.getId(), "VM");
                                networkCardDao.deleteByHost(server.getId(), "VM", userId);
                                cloudServerDao.remove(id, userId);
                                serverIpDao.removebyuuid(server.getUuid());
                                event = new ResourceEvent(id, "DELETE", "success", userId, new Date(), "VM");
                            } else {
                                event = new ResourceEvent(id, "DELETE", "fail", userId, new Date(), "VM");
                            }
                            resourceEventDao.save(event);
                            resourceEventPublisher.send(new OperateResult(bsmResult.isSuccess(), bsmResult.getMessage(),
                                    operate, MapTools.simpleMap("vendorId", cloudVendor.getId()), userId));
                        }
                    } catch (Exception e) {
                        logger.error("删除虚拟机失败", e);
                        resourceEventPublisher.send(new OperateResult(false, "删除虚拟机失败", operate,
                                MapTools.simpleMap("vendorId", cloudVendor.getId()), userId));
                    }
                }
            }).start();
            return new BsmResult(true, "删除任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("remove CloudServer fail:", e);
            return new BsmResult(false, "删除失败");
        } finally {
            if (null != lock) {
                lock.release();
            }
        }
    }

    @Override
    public BsmResult detail(Long id) {
        try {
            CloudServer server = cloudServerDao.query(id);
            // 设置模板名称
            if (null != server.getTemplateId()) {
                CloudServer temp = cloudServerDao.get(server.getTemplateId());
                if (null != temp) {
                    server.setTemplate(temp.getName());
                }
            }
            // 设置主机名称
            HostSystem hostSystem = hostSystemDao.query(server.getHostId());
            if (null != hostSystem) {
                server.setHostName(hostSystem.getName());
                server.setClusterName(hostSystem.getClusterName());
            }
            // 设置快照数量
            List<Snapshot> snapshots = snapshotDao.listByVMid(server.getId());
            server.setSnapshotCount(snapshots.size());
            // 网络适配器
            List<NetworkCard> cards = networkCardDao.listByHost(id, "VM");
            server.setNetcards(cards);
            return new BsmResult(true, server, "查询成功!");
        } catch (Exception e) {
            logger.error("get cloudserver failure:", e);
            return new BsmResult(false, "查询失败!");
        }
    }

    private BsmResult handler(Long id, Long userId, String handler) {
        String path = CloudServer.class.getSimpleName() + "_" + id;
        HarmonyLock lock = null;
        try {
            lock = lockFactory.getLock(path);
            if (!lock.acquire(path, 10, TimeUnit.SECONDS)) {
                logger.warn("Get harmonyLock time out!");
                return new BsmResult(false, "请求超时");
            }
            CloudServer server = cloudServerDao.get(id);
            if (null == server) {
                logger.warn("CloudServer data not exist");
                return new BsmResult(false, "数据不存在");
            }
            // 云供应商
            CloudVendor vendor = cloudVendorDao.query(server.getVendorId());
            if (null == vendor) {
                return new BsmResult(false, "获取云供应商失败");
            }
            CloudHandler cloudHandler = CloudHandler.valueOf(handler.toUpperCase());
            VendorType type = VendorType.valueOf(vendor.getType());
            switch (type) {
            case VMWARE:
                switch (cloudHandler) {
                case START:
                    HostSystem host = hostSystemDao.query(server.getHostId());
                    if (null == host) {
                        logger.warn("HostSystem data not exist");
                        return new BsmResult(false, "宿主机不存在");
                    }
                    if (host.isMaintain()) {
                        return new BsmResult(false, "该虚拟机所在宿主机处于维护模式下，无法执行开机任务");
                    }
                    break;
                case REBOOT:
                    if (!server.getToolsInstalled()) {
                        logger.warn("CloudServer's vmwareTools not running");
                        return new BsmResult(false, "该虚拟机没有安装VMTools，无法执行重启任务");
                    } /*
                       * else if (!server.getToolsRunning()) { return new
                       * BsmResult(false, "该虚拟机VMTools没有启动，无法执行重启任务"); }
                       */
                default:
                    break;
                }
                break;
            case OPENSTACK:
                break;
            default:
                break;
            }
            this.ServerHandler(cloudHandler, server, vendor, userId, "");
            return new BsmResult(true, "虚拟机操作任务已下发，正在执行中……");
        } catch (Exception e) {
            logger.error("handle server fail:", e);
            return new BsmResult(false, "虚拟机操作失败");
        } finally {
            if (null != lock) {
                lock.release();
            }
        }
    }

    @Override
    public BsmResult start(Long id, Long userId) {
        return this.handler(id, userId, CloudHandler.START.name());
    }

    @Override
    public BsmResult stop(Long id, Long userId) {
        return this.handler(id, userId, CloudHandler.STOP.name());
    }

    @Override
    public BsmResult restart(Long id, Long userId) {
        return this.handler(id, userId, CloudHandler.REBOOT.name());
    }

    @Override
    public BsmResult backup(Long id, Long userId) {
        // TODO
        return new BsmResult(true, null, "调用成功，但是TODO:");
    }

    @Override
    public BsmResult recovery(Long id, Long userId) {
        return this.handler(id, userId, CloudHandler.RECOVERY.name());
    }

    @Override
    public BsmResult pause(Long id, Long userId) {
        return this.handler(id, userId, CloudHandler.PAUSE.name());
    }

    /**
     * 云操作处理
     * 
     * @param handler
     * @param server
     * @param cloudVendor
     * @param userId
     * @param code
     * @return
     * @throws Exception
     */
    private void ServerHandler(CloudHandler handler, CloudServer server, CloudVendor cloudVendor, Long userId,
            String code) throws Exception {
        String vendor = cloudVendor.getUuid();
        String instanceId = server.getInstanceId();
        String status = null;

        switch (handler) {
        case START:
            status = VMStatus.STARTING.name();
            break;
        case STOP:
            status = VMStatus.STOPPING.name();
            break;
        case REBOOT:
            status = VMStatus.RESTARTING.name();
            break;
        case SUSPEND:
            status = VMStatus.SUSPENDING.name();
            break;
        case RECOVERY:
            status = VMStatus.RECOVERING.name();
            break;
        case UNPAUSE:
            status = VMStatus.RECOVERING.name();
            break;
        default:
            break;
        }
        server.setStatus(status);
        server.setMenderId(userId);
        try {
            cloudServerDao.update(server);
        } catch (Exception e) {
        }
        new Thread(new Runnable() {
            public void run() {
                BsmResult result = new BsmResult(false, "暂不支持该操作");
                String state = null;
                switch (handler) {
                case START:
                    result = serverProvider.start(instanceId, vendor, code);
                    state = VMStatus.STARTING.name();
                    break;
                case STOP:
                    result = serverProvider.stop(instanceId, vendor, code);
                    state = VMStatus.STOPPING.name();
                    break;
                case REBOOT:
                    result = serverProvider.reboot(instanceId, vendor, code);
                    state = VMStatus.RESTARTING.name();
                    break;
                case SUSPEND:
                    result = serverProvider.suspend(instanceId, vendor, code);
                    state = VMStatus.SUSPENDING.name();
                    break;
                case RECOVERY:
                    result = serverProvider.resume(instanceId, vendor, code);
                    state = VMStatus.RECOVERING.name();
                    break;
                case UNPAUSE:
                    result = serverProvider.unpause(instanceId, vendor, code);
                    state = VMStatus.RECOVERING.name();
                    break;
                default:
                    break;
                }
                String operate = cloudVendor.getType().toLowerCase() + ".vm";
                ResourceEvent event = null;
                try {
                    updateStatus(code, handler, cloudVendor, server, state);
                    cloudServerDao.update(server);
                    if (result.isSuccess()) {
                        event = new ResourceEvent(server.getId(), handler.name(), "success", userId, new Date(), "VM");
                    } else {
                        event = new ResourceEvent(server.getId(), handler.name(), "fail", userId, new Date(), "VM");
                    }
                    resourceEventDao.save(event);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), result.getMessage(), operate,
                            MapTools.simpleMap("vendorId", cloudVendor.getId()), userId));
                } catch (Exception e) {
                    logger.error("update status failure:", e);
                    resourceEventPublisher.send(new OperateResult(false, "虚拟机操作失败", operate,
                            MapTools.simpleMap("vendorId", cloudVendor.getId()), userId));
                }
            }
        }).start();
    }

    /**
     * 更新状态
     * 
     * @param type
     * @param code
     * @param operate
     * @param vendor
     * @param server
     * @return
     * @throws Exception
     */
    private void updateStatus(String code, CloudHandler handler, CloudVendor vendor, CloudServer server, String status)
            throws Exception {
        String type = vendor.getType();
        Long start = System.currentTimeMillis();
        Map<String, Long> hostIdMap = getHostId(vendor.getId());// 添加hostId
        boolean running = true;
        while (running) {
            BsmResult result = serverProvider.detail(server.getInstanceId(), vendor.getUuid(), code);
            // 超时和延时
            if (System.currentTimeMillis() - start > 1000 * 60 * 10) {
                server.setStatus(VMStatus.EXCEPTION.name());
                running = false;
            }
            if (result.isSuccess()) {
                VMBean bean = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), VMBean.class);
                if (!bean.getInstanceId().equals(server.getInstanceId())) {
                    continue;
                }
                if (type.equals(VendorType.ALIYUN.name())) {
                    switch (handler) {
                    case START:
                        if (bean.getStatus().equalsIgnoreCase("Running")) {
                            server.setStatus(VMStatus.RUNNING.name());
                        }
                        break;
                    case STOP:
                        if (bean.getStatus().equalsIgnoreCase("Stopped")) {
                            server.setStatus(VMStatus.STOPPED.name());
                        }
                        break;
                    case REBOOT:
                        if (bean.getStatus().equalsIgnoreCase("Running")) {
                            server.setStatus(VMStatus.RUNNING.name());
                        }
                        break;
                    default:
                        break;
                    }
                } else if (type.equals(VendorType.JDYUN.name())) {
                    switch (handler) {
                    case START:
                        if (bean.getStatus().equalsIgnoreCase("active")) {
                            server.setStatus(VMStatus.RUNNING.name());
                        }
                        break;
                    case STOP:
                        if (bean.getStatus().equalsIgnoreCase("stopped")) {
                            server.setStatus(VMStatus.STOPPED.name());
                        }
                        break;
                    case REBOOT:
                        if (bean.getStatus().equalsIgnoreCase("active")) {
                            server.setStatus(VMStatus.RUNNING.name());
                        }
                        break;
                    default:
                        break;
                    }
                } else if (type.equals(VendorType.OPENSTACK.name())) {
                    switch (handler) {
                    case START:
                        if (bean.getStatus().equalsIgnoreCase("RUNNING")) {
                            server.setStatus(VMStatus.RUNNING.name());
                            server.setHostName(bean.getHostName());
                            server.setHostId(hostIdMap.get(bean.getHostName()));
                        }
                        break;
                    case STOP:
                        if (bean.getStatus().equalsIgnoreCase("STOPPED")) {
                            server.setStatus(VMStatus.STOPPED.name());
                            server.setHostName(bean.getHostName());
                            server.setHostId(hostIdMap.get(bean.getHostName()));
                        }
                        break;
                    case REBOOT:
                        if (bean.getStatus().equalsIgnoreCase("RUNNING")) {
                            server.setStatus(VMStatus.RUNNING.name());
                            server.setHostName(bean.getHostName());
                            server.setHostId(hostIdMap.get(bean.getHostName()));
                        }
                        break;
                    case RECOVERY:
                        if (bean.getStatus().equalsIgnoreCase("RUNNING")) {
                            server.setStatus(VMStatus.RUNNING.name());
                            server.setHostName(bean.getHostName());
                            server.setHostId(hostIdMap.get(bean.getHostName()));
                        }
                        break;
                    case UNPAUSE:
                        if (bean.getStatus().equalsIgnoreCase("RUNNING")) {
                            server.setStatus(VMStatus.RUNNING.name());
                            server.setHostName(bean.getHostName());
                            server.setHostId(hostIdMap.get(bean.getHostName()));
                        }
                    default:
                        break;
                    }
                } else if (type.equals(VendorType.VMWARE.name())) {
                    switch (handler) {
                    case START:
                        if (bean.getStatus().equalsIgnoreCase("poweredOn")) {
                            server.setStatus(VMStatus.RUNNING.name());
                        }
                        break;
                    case STOP:
                        if (bean.getStatus().equalsIgnoreCase("poweredOff")) {
                            server.setStatus(VMStatus.STOPPED.name());
                        }
                        break;
                    case REBOOT:
                        if (bean.getStatus().equalsIgnoreCase("poweredOn")) {
                            server.setStatus(VMStatus.RUNNING.name());
                        }
                        break;
                    case SUSPEND:
                        if (bean.getStatus().equalsIgnoreCase("suspended")) {
                            server.setStatus(VMStatus.SUSPENDED.name());
                        }
                    default:
                        break;
                    }
                }
                if (!server.getStatus().equalsIgnoreCase(status)) {
                    running = false;
                }
                Thread.sleep(3000L);
            }
        }
    }

    @Override
    public BsmResult suspend(Long id, Long userId) {
        return this.handler(id, userId, CloudHandler.SUSPEND.getName());
    }

    @Override
    public BsmResult active(Long id, Long userId) {
        return this.handler(id, userId, CloudHandler.ACTIVE.getName());
    }

    /**
     * 通过IP查询当前云主机信息
     * 
     * @author sxp
     * @since V1.0 Nov 4, 2016
     */
    @Override
    public CloudServer detail(String ip) {
        try {
            return this.cloudServerDao.get(ip);
        } catch (Exception e) {
            logger.error("Query cloudServer information by IP fail.", e);
            return null;
        }
    }

    @Override
    public List<Map<String, String>> getAll4Snmp() {
        try {
            return this.cloudServerDao.getAll4Snmp();
        } catch (Exception e) {
            logger.error("get all 4snmp:", e);
            return new ArrayList<>();
        }
    }

    @Override
    public BsmResult getPerformance(String params) {
        // 获取所有的
        JSONObject object = JSONTools.isJSONObj(params);
        Long vendorId = object.getLong("vendorId");
        String name = object.getString("name");// 名称
        String type = object.getString("type");// 类型
        String time = object.getString("time");// 时间间隔
        try {
            CloudVendor vendor = this.cloudVendorDao.query(vendorId);
            if (null == vendor) {
                logger.warn("CloudVendor does not exist!");
                return new BsmResult(false, "供应商不存在");
            }
            if (VendorType.OPENSTACK.toString().equals(vendor.getType())) {
                logger.info("开始获取虚拟机性能数据-----------------\n");
                return new ZTEServerPerf().serverperf(type, name, time);
            }
            BsmResult result = monitorProvider.query(vendor.getUuid(), name, "VirtualMachine", type, time);
            if (result.isSuccess()) {
                if (type.equals("DISK")) {
                    return result;
                } else {
                    MonitorModel model = JSONObject.parseObject(JSONObject.toJSONString(result.getData()),
                            MonitorModel.class);
                    List<MonitorCategoryModel> monitors = model.getValues();
                    List<MonitorCategoryModel> values = Lists.newArrayList();
                    for (MonitorCategoryModel monitor : monitors) {
                        List<String> oldDatas = monitor.getData();
                        List<String> newDatas = Lists.newArrayList();
                        for (String data : oldDatas) {
                            newDatas.add(new BigDecimal(Float.valueOf(data))
                                    .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP).toString());
                        }
                        values.add(new MonitorCategoryModel(monitor.getName(), newDatas));
                    }

                    MonitorModel monitorModel = new MonitorModel(model.getKeys(), values);
                    return new BsmResult(result.isSuccess(), monitorModel, result.getMessage());
                }
            }
            return result;
        } catch (Exception e) {
            logger.error("查询数据失败", e);
            return new BsmResult(false, "查询失败");
        }
    }

    @Override
    public BsmResult vncconsole(String params) {
        // 获取所有的
        JSONObject object = JSONTools.isJSONObj(params);
        String vncType = object.getString("vncType");
        String serverId = object.getString("serverId");
        Long vendorId = object.getLong(Common.ID);
        String region = object.getString(Common.REGION);
        try {
            CloudVendor vendor = this.cloudVendorDao.query(vendorId);
            BsmResult result = serverProvider.VNCConsole(vncType, serverId, vendor.getUuid(), region);
            if (result.isSuccess()) {
                return result;
            }
        } catch (Exception e) {
            logger.error("查询数据失败", e);
            return new BsmResult(false, "查询失败");
        }
        return new BsmResult(false, "vnc链接失败！");
    }

    @Override
    public BsmResult networks(Long hostId) {
        try {
            List<NetworkHost> networkHosts = networkHostDao.list(hostId, "PM");
            List<String> networks = Lists.newArrayList();
            for (NetworkHost networkHost : networkHosts) {
                Network network = networkDao.query(networkHost.getNetworkId());
                if (null == network) {
                    continue;
                }
                if ("VSWITCH".equals(network.getType())) {
                    networks.add(network.getName());
                } else {
                    List<PortGroup> groups = portGroupDao.listByNetwork(network.getId());
                    for (PortGroup group : groups) {
                        if ("DVPORT".equals(group.getType())) {
                            networks.add(group.getName());
                        }
                    }
                }
            }
            return new BsmResult(true, networks, "查询成功");
        } catch (Exception e) {
            logger.error("List network error", e);
            return new BsmResult(false, "查询失败");
        }
    }

    @Override
    public BsmResult serverIps(String instanceId) {
        List<ServerIp> serverIps;
        try {
            serverIps = serverIpDao.querybyuuid(instanceId);
            return new BsmResult(true, serverIps, "查询成功");
        } catch (Exception e) {
            logger.error("List Error {}", e);
            return new BsmResult(false, "查询失败！");
        }

    }

    @Override
    public BsmResult unpause(Long id, Long userId) {
        return this.handler(id, userId, CloudHandler.UNPAUSE.name());
    }

    private Map<String, Long> getHostId(Long id) throws Exception {
        List<HostSystem> hostsystems = hostSystemDao.listByVendor(id);
        Map<String, Long> hostIdMap = Maps.newConcurrentMap();
        if (ListTool.isEmpty(hostsystems)) {
            return null;
        }
        for (HostSystem hostSystem : hostsystems) {
            hostIdMap.put(hostSystem.getName(), hostSystem.getId());
        }
        return hostIdMap;
    }
}